﻿#include "wnodemanager.h"
#include "../cmainframe.h"
#include "../common.h"
#include "../network/wtcpclient.h"
#include "../gui/guimanager.h"
#include "../locomanager/locomanager.h"
#include "crouteconditions.h"

initialiseSingleton(WNodeManager);

void tagSectNode::clearLock(void)
{
    std::map<int,wxVector<WBaseNode*>>::iterator iter = nodes.begin();
    for(;iter != nodes.end();++iter)
    {
        for(int i=0;i<(*iter).second.size();i++)
        {
            if((*iter).second[i]->getOperState() == NodeOperState::LOCKED)
                (*iter).second[i]->setOperState(NodeOperState::NORMAL);
        }
    }

    operstate = NodeOperState::NORMAL;
    signalstate = NodeSignalState::CLEAR;

    WNodeManager::getSingleton().slot_processSwitchChangeToSect();
}

wxColour tagSectNode::getStateColor(void)
{
    wxColour decColour = wxColour(255,255,255,255);

    // 先判断操作条件
    switch(operstate)
    {
    case NodeOperState::CHOSEN:            // 选中
        decColour = wxColour(165, 42, 42,255);
        break;
    case NodeOperState::LOCKED:            // 锁闭
        decColour = wxColour(0, 255, 0,255);
        break;
    default:
        break;
    }

    // 信号条件
    switch(signalstate)
    {
    case NodeSignalState::OCCUPY:             // 占用
        decColour = wxColour(255, 0, 0,255);
        break;
    case NodeSignalState::NOSIGNAL:           // 没信号
        decColour = wxColour(255, 255, 0,255);
        break;
    default:
        break;
    }

    return decColour;
}

// 检测进路是否在区段中
int tagSectNode::isInSect(std::vector<tagSLRouteNode*> decnodes,int *startPosition)
{
    if(decnodes.empty() ||
        nodes.empty())
        return -1;

    std::map<int,wxVector<WBaseNode*>>::iterator iter = nodes.begin();
    for(;iter != nodes.end();++iter)
    {
        if((*iter).second.empty())
            continue;

        int index = *startPosition;
        bool isOk = true;

        for(int k=0;k<(*iter).second.size();k++)
        {
            if(index >= decnodes.size() ||
               decnodes[index]->node != (*iter).second[k])
            {
                isOk = false;
                break;
            }

            index+=1;
        }

        if(isOk)
        {
            // 越过中间的挂接点
            for(int i=index;i<decnodes.size();i++)
            {
                if(decnodes[i]->node->getNodeType() != NodeType::NODE_MOUNT)
                {
                    index = i;
                    break;
                }
            }

            *startPosition = index;
            return (*iter).first;
        }
    }

    return -1;
}

void tagRoute::clearAllSect(void)
{
    std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iter = sectNodes.begin();
    for(;iter != sectNodes.end();++iter)
    {
        for(int i=0;i<(*iter).second.size();i++)
        {
            tagSectNode* pSectNode = WNodeManager::getSingleton().getSect((*iter).second[i].sectName);
            if(pSectNode != NULL &&
                pSectNode->signalstate == NodeSignalState::CLEAR && pSectNode->lastsignalstate == NodeSignalState::OCCUPY)
            {
                pSectNode->operstate = NodeOperState::NORMAL;
            }
        }
    }
}

wxString tagRoute::closeAllLights(wxString sectName)
{
    std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iter = sectNodes.find(sectName);
    if(iter == sectNodes.end())
        return "";

    wxString sendMsg = wxT("{\"signal\":{\"信号灯\":[");

    int tmpCount = 0;
    iter = sectNodes.begin();
    for(;iter != sectNodes.end();++iter)
    {
        if((*iter).second.empty() ||
            (*iter).second[0].node->getNodeType() != NodeType::NODE_SIGNAL ||
            (*iter).second[0].node->getSignalState() != NodeSignalState::OCCUPY)
            continue;

        //(*iter).second[0].node->setSignalState(NodeSignalState::CLEAR);

        sendMsg += wxString::Format(wxT("{\"%d\":\"蓝灯\"},"),(*iter).second[0].node->getDeviceID());
        tmpCount+=1;
    }

    if(tmpCount > 0) sendMsg = sendMsg.Mid(0,sendMsg.length()-1)+wxT("]}}");
    else sendMsg += wxT("]}}");

    return tmpCount > 0 ? sendMsg : "";
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

WNodeManager::WNodeManager()
    : mLockedScreen(false)
{

}

WNodeManager::~WNodeManager()
{
    deleteAllNodes();
}

/// 保存json配置
bool WNodeManager::saveJsonConfig(wxString configfilepath)
{
    if(configfilepath == "")
        configfilepath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath() + wxT("/resources/scripts/站场配置.lua");

    wxString stationConfigString;

    // 创建 cJSON 对象
    cJSON *root = cJSON_CreateObject();

    cJSON *nodes = cJSON_CreateArray();
    std::map<wxString,WBaseNode*> allnodes = WNodeManager::getSingleton().getAllNodes();
    std::map<wxString,WBaseNode*>::iterator iter = allnodes.begin();
    for(;iter != allnodes.end();++iter)
    {
        cJSON *node = cJSON_CreateObject();
        cJSON_AddNumberToObject(node, "nodetype", (int)(*iter).second->getNodeType());
        cJSON_AddStringToObject(node, "nodename", (*iter).second->getName().ToUTF8().data());
        cJSON_AddNumberToObject(node, "deviceid", (*iter).second->getDeviceID());
        cJSON *position = cJSON_AddObjectToObject(node, "position");
        cJSON_AddNumberToObject(position, "x", (*iter).second->getPosition().x);
        cJSON_AddNumberToObject(position, "y", (*iter).second->getPosition().y);

        switch((*iter).second->getNodeType())
        {
        case NodeType::NODE_SIGNAL:
        {
            WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>((*iter).second);
            if(pWSignalLampNode)
            {
                cJSON_AddNumberToObject(node, "direction", (int)pWSignalLampNode->getNameAlignment());
                cJSON_AddNumberToObject(node, "routetype", (int)pWSignalLampNode->getRouteType());
            }
        }
            break;
        case NodeType::NODE_SWITCH:
        {
            WSwitchNode *pWSwitchNode = static_cast<WSwitchNode*>((*iter).second);
            if(pWSwitchNode)
            {
                wxString decString;
                std::map<SwitchState,SwitchStateMounts> mounts = pWSwitchNode->getAllSwitchStateMounts();
                std::map<SwitchState,SwitchStateMounts>::iterator iter2 = mounts.begin();
                for(;iter2 != mounts.end();++iter2)
                {
                    decString += wxString::Format("%d:%s-%s;",
                                                  (*iter2).first,
                                                  (*iter2).second.startMount->name,
                                                  (*iter2).second.endMount->name);
                }

                if(decString != "") decString = decString.Mid(0,decString.size()-1);

                cJSON_AddStringToObject(node, "switchstate", decString.ToUTF8().data());
            }
        }
            break;
        default:
            break;
        }

        cJSON_AddItemToArray(nodes, node);
    }
    cJSON_AddItemToObject(root, "nodes", nodes);

    cJSON *mountpointsArr = cJSON_CreateArray();
    allnodes = WNodeManager::getSingleton().getAllNodes();
    iter = allnodes.begin();
    for(;iter != allnodes.end();++iter)
    {
        std::map<wxString,tagMountPoint> mountpoints = (*iter).second->getAllMountPoints();

        if(!mountpoints.empty())
        {
            std::map<wxString,tagMountPoint>::iterator itermount = mountpoints.begin();

            cJSON *mount = cJSON_CreateObject();
            cJSON_AddStringToObject(mount, "nodename", (*iter).second->getName().ToUTF8().data());
            cJSON *mounts = cJSON_CreateArray();

            for(;itermount != mountpoints.end();++itermount)
            {
                cJSON *mountobj = cJSON_CreateObject();
                cJSON_AddStringToObject(mountobj, "mountname", (*itermount).second.name.ToUTF8().data());
                cJSON_AddStringToObject(mountobj, "mountnode", (*itermount).second.node->getName().ToUTF8().data());
                cJSON *position = cJSON_AddObjectToObject(mountobj, "mountpos");
                cJSON_AddNumberToObject(position, "x", (*itermount).second.pos.x);
                cJSON_AddNumberToObject(position, "y", (*itermount).second.pos.y);
                cJSON_AddNumberToObject(mountobj, "level", (*itermount).second.level);
                cJSON_AddNumberToObject(mountobj, "orientation", (*itermount).second.direction);

                cJSON_AddItemToArray(mounts, mountobj);
            }

            cJSON_AddItemToObject(mount, "mounts", mounts);
            cJSON_AddItemToArray(mountpointsArr, mount);
        }
    }
    cJSON_AddItemToObject(root, "mountpoints", mountpointsArr);

    cJSON *sects = cJSON_CreateArray();

    std::map<wxString,tagSectNode*> allsects = WNodeManager::getSingleton().getAllSects();
    std::map<wxString,tagSectNode*>::iterator itersect = allsects.begin();
    for(;itersect != allsects.end();++itersect)
    {
        cJSON *sectobj = cJSON_CreateObject();
        cJSON_AddStringToObject(sectobj, "sectname", (*itersect).first.ToUTF8().data());

        wxString decrange;
        std::map<int,wxVector<WBaseNode*>>::iterator itersectnodes = (*itersect).second->nodes.begin();
        for(;itersectnodes != (*itersect).second->nodes.end();++itersectnodes)
        {
            if((*itersectnodes).second.size() > 1)
                decrange += wxString::Format(wxT("%s-%s;"),(*itersectnodes).second[0]->getName(),
                                             (*itersectnodes).second[(*itersectnodes).second.size()-1]->getName());
        }

        if(!decrange.IsEmpty())
            decrange = decrange.Mid(0,decrange.size()-1);
        cJSON_AddStringToObject(sectobj, "range", decrange.ToUTF8().data());

        cJSON_AddNumberToObject(sectobj, "deviceid", (*itersect).second->deviceID);

        wxString lastsect;
        for(int i=0;i<(*itersect).second->lastsects.size();i++)
        {
            lastsect += wxString::Format(wxT("%s;"),(*itersect).second->lastsects[i]);
        }

        if(!lastsect.IsEmpty()) lastsect = lastsect.Mid(0,lastsect.size()-1);
        cJSON_AddStringToObject(sectobj, "lastsect", lastsect.ToUTF8().data());

        wxString nextsect;
        for(int i=0;i<(*itersect).second->nextsects.size();i++)
        {
            nextsect += wxString::Format(wxT("%s;"),(*itersect).second->nextsects[i]);
        }

        if(!nextsect.IsEmpty()) nextsect = nextsect.Mid(0,nextsect.size()-1);
        cJSON_AddStringToObject(sectobj, "nextsect", nextsect.ToUTF8().data());

        cJSON_AddNumberToObject(sectobj, "accessrule", (int)(*itersect).second->accessrule);

        cJSON_AddItemToArray(sects, sectobj);
    }

    cJSON_AddItemToObject(root, "sects", sects);

    cJSON *routecondi = cJSON_CreateArray();

    std::map<wxString,std::map<wxString,tagRouteCondiItem>> allrouteconditions = CRouteConditions::getSingleton().getAllRouteConditions();
    std::map<wxString,std::map<wxString,tagRouteCondiItem>>::iterator itercondition = allrouteconditions.begin();
    for(;itercondition != allrouteconditions.end();++itercondition)
    {
        cJSON *routecondition = cJSON_CreateObject();

        std::map<wxString,tagRouteCondiItem>::iterator iterconditionitem = (*itercondition).second.begin();
        for(;iterconditionitem != (*itercondition).second.end();++iterconditionitem)
        {
            cJSON_AddStringToObject(routecondition, "startlight", (*itercondition).first.ToUTF8().data());
            cJSON_AddStringToObject(routecondition, "endlight", (*iterconditionitem).first.ToUTF8().data());
            cJSON *conflictsignals = cJSON_CreateArray();

            for(int i=0;i<(*iterconditionitem).second.conflictsignals.size();i++)
                cJSON_AddItemToArray(conflictsignals, cJSON_CreateString((*iterconditionitem).second.conflictsignals[i]->getName()));

            cJSON_AddItemToObject(routecondition, "conflictsignal", conflictsignals);

            cJSON *conflictswitchs = cJSON_CreateArray();

            for(int i=0;i<(*iterconditionitem).second.conflictswitch.size();i++)
            {
                cJSON *conflictswitchobj = cJSON_CreateObject();
                cJSON_AddStringToObject(conflictswitchobj,
                                        (*iterconditionitem).second.conflictswitch[i].switchnode->getName().ToUTF8().data(),
                                        (*iterconditionitem).second.conflictswitch[i].switchstate == SwitchState::POSITIVE ? "定位" : "反位");

                cJSON_AddItemToArray(conflictswitchs, conflictswitchobj);
            }

            cJSON_AddItemToObject(routecondition, "conflictswitch", conflictswitchs);

            cJSON *followswitchs = cJSON_CreateArray();

            for(int i=0;i<(*iterconditionitem).second.followswitch.size();i++)
            {
                cJSON *followswitchobj = cJSON_CreateObject();
                cJSON_AddStringToObject(followswitchobj,
                                        (*iterconditionitem).second.followswitch[i].switchnode->getName().ToUTF8().data(),
                                        (*iterconditionitem).second.followswitch[i].switchstate == SwitchState::POSITIVE ? "定位" : "反位");

                cJSON_AddItemToArray(followswitchs, followswitchobj);
            }

            cJSON_AddItemToObject(routecondition, "followswitch", followswitchs);
        }

        cJSON_AddItemToArray(routecondi, routecondition);
    }

    cJSON_AddItemToObject(root, "routecondi", routecondi);

    cJSON *guis = cJSON_CreateArray();

    std::map<int,GuiBaseNode*> allguibasenodes = GuiManager::getSingleton().getAllBaseNodes();
    std::map<int,GuiBaseNode*>::iterator iterguinode = allguibasenodes.begin();
    for(;iterguinode != allguibasenodes.end();++iterguinode)
    {
        cJSON *guinode = cJSON_CreateObject();

        switch((*iterguinode).second->getNodeType())
        {
        case GuiNodeType::GUINODETYPE_BUTTON:
        {
            cJSON_AddStringToObject(guinode, "nodetype", "按钮");
        }
            break;
        default:
            break;
        }

        cJSON_AddNumberToObject(guinode,"id",(*iterguinode).second->getID());
        cJSON_AddStringToObject(guinode, "name", (*iterguinode).second->getNodeName().ToUTF8().data());
        cJSON_AddStringToObject(guinode, "tip", (*iterguinode).second->getTipText().ToUTF8().data());
        cJSON_AddStringToObject(guinode, "rect",
                                wxString::Format("%d,%d,%d,%d",(*iterguinode).second->getRect().GetX(),
                                                               (*iterguinode).second->getRect().GetY(),
                                                               (*iterguinode).second->getRect().GetWidth(),
                                                               (*iterguinode).second->getRect().GetHeight()));

        wxColour pnormalcol,povercol,pclickcol;
        (*iterguinode).second->geColor(&pnormalcol,&povercol,&pclickcol);
        wxColour pbordercol = (*iterguinode).second->getBorderColor();

        cJSON_AddStringToObject(guinode, "normalcolor",
                                wxString::Format("%d,%d,%d,%d",pnormalcol.GetRed(),
                                                               pnormalcol.GetGreen(),
                                                               pnormalcol.GetBlue(),
                                                               pnormalcol.GetAlpha()).ToUTF8().data());
        cJSON_AddStringToObject(guinode, "overcolor",
                                wxString::Format("%d,%d,%d,%d",povercol.GetRed(),
                                                 povercol.GetGreen(),
                                                 povercol.GetBlue(),
                                                 povercol.GetAlpha()).ToUTF8());
        cJSON_AddStringToObject(guinode, "clickcolor",
                                wxString::Format("%d,%d,%d,%d",pclickcol.GetRed(),
                                                 pclickcol.GetGreen(),
                                                 pclickcol.GetBlue(),
                                                 pclickcol.GetAlpha()).ToUTF8());
        cJSON_AddStringToObject(guinode, "bordercolor",
                                wxString::Format("%d,%d,%d,%d",pbordercol.GetRed(),
                                                 pbordercol.GetGreen(),
                                                 pbordercol.GetBlue(),
                                                 pbordercol.GetAlpha()).ToUTF8());

        cJSON_AddItemToArray(guis, guinode);
    }

    cJSON_AddItemToObject(root, "guis", guis);

    // 将 cJSON 对象转换为字符串
    char *json_string = cJSON_Print(root);
    if (json_string != NULL) {

        stationConfigString = wxString::Format(wxT("stationConfig = [[%s]];"),wxString::FromUTF8(json_string));

        // 释放字符串内存
        free(json_string);
    }

    // 释放 cJSON 对象内存
    cJSON_Delete(root);

    wxFile decfile;
    if (decfile.Create(configfilepath, true))
    {
        wxCSConv conv("UTF-8");

        if (!decfile.Write(stationConfigString,conv)) {
            decfile.Close();
            return false;
        }

        decfile.Close();
    }

    return true;
}

bool WNodeManager::loadJsonConfig(const char* configstr)
{
    if(configstr == "") return false;

    // 先清空所有数据
    this->clear();
    GuiManager::getSingleton().deleteAllNodes();
    LocoManager::getSingleton().deleteAllLocos();
    CRouteConditions::getSingleton().clearAllData();

    // 解析 JSON 字符串
    cJSON *doc = cJSON_Parse(configstr);
    if (!doc) {
        const char *error_ptr = cJSON_GetErrorPtr();
        wxString pErrorStr = wxString::Format(wxT("JSON 解析失败:错误位置: %s"),
                                              error_ptr ? wxString::FromUTF8(error_ptr) : wxT("未知"));
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR, pErrorStr.ToUTF8().data());
        return false;
    }

    // 获取根对象
    cJSON *root = doc;
    std::vector<wxString> decfiles;
    std::map<WBaseNode*,std::map<SwitchState,tagSwitchRoute>> tmpSwitchRoutes;
    wxCSConv gb2312Conv(wxFONTENCODING_UTF8);

    // 获取所有的结点
    cJSON *nodes = cJSON_GetObjectItemCaseSensitive(root, "nodes");
    if (nodes && cJSON_IsArray(nodes)) {
        cJSON *node_item = NULL;
        cJSON_ArrayForEach(node_item, nodes) {
            cJSON *nodenameval = cJSON_GetObjectItemCaseSensitive(node_item, "nodename");
            cJSON *nodetypeval = cJSON_GetObjectItemCaseSensitive(node_item, "nodetype");
            cJSON *positionval = cJSON_GetObjectItemCaseSensitive(node_item, "position");
            cJSON *directionval = cJSON_GetObjectItemCaseSensitive(node_item, "direction");
            cJSON *defaultrouteval = cJSON_GetObjectItemCaseSensitive(node_item, "switchstate");
            cJSON *routetypeval = cJSON_GetObjectItemCaseSensitive(node_item, "routetype");
            cJSON *deviceid = cJSON_GetObjectItemCaseSensitive(node_item, "deviceid");

            if (!nodenameval || !nodetypeval || !positionval) {
                continue;  // 跳过无效的结点
            }

            NodeType pNodeType = (NodeType)static_cast<int>(cJSON_GetNumberValue(nodetypeval));
            wxString pNodeName = wxString(cJSON_GetStringValue(nodenameval),gb2312Conv);

            cJSON *positionXval = cJSON_GetObjectItemCaseSensitive(positionval, "x");
            cJSON *positionYval = cJSON_GetObjectItemCaseSensitive(positionval, "y");

            if (!positionXval || !positionYval) {
                continue;  // 跳过无效的位置数据
            }

            wxRealPoint pNodePosition = wxRealPoint(
                cJSON_GetNumberValue(positionXval),
                cJSON_GetNumberValue(positionYval)
            );

            decfiles.push_back(pNodeName);

            switch (pNodeType)
            {
            case NODE_MOUNT:     // 挂接点
            {
                WMountNode* pMountNode = this->addMountNode(pNodeName, pNodePosition);
                if(pMountNode != NULL)
                {
                    //pMountNode->setDeviceID(deviceid != NULL ? cJSON_GetNumberValue(deviceid) : this->getAllNodes().size());
                }
            }
                break;
            case NODE_SIGNAL:    // 信号灯
            {
                WSignalLampNode* pSignalLampNode = this->addSignalLamp(pNodeName, pNodePosition);
                if(pSignalLampNode != NULL &&
                   directionval != NULL &&
                   routetypeval != NULL)
                {
                    pSignalLampNode->setNameAlignment((TextAlignment)static_cast<int>(cJSON_GetNumberValue(directionval)));
                    pSignalLampNode->setRouteType((SLRouteType)static_cast<int>(cJSON_GetNumberValue(routetypeval)));
                    pSignalLampNode->setDeviceID(deviceid != NULL ? cJSON_GetNumberValue(deviceid) : this->getAllNodes().size());
                }
            }
                break;
            case NODE_SWITCH:    // 道岔
            {
                WSwitchNode* pSwitchNode = this->addSwitch(pNodeName, pNodePosition);
                if(pSwitchNode != NULL && defaultrouteval != NULL)
                {
                    wxArrayString paramarray = SplitString(wxString(cJSON_GetStringValue(defaultrouteval),gb2312Conv),
                                                           ";");
                    for(int k=0;k<paramarray.size();k++)
                    {
                        wxArrayString paramarray1 = SplitString(paramarray[k],":");
                        if(paramarray1.size() == 2)
                        {
                            wxArrayString paramarray2 = SplitString(paramarray1[1],"-");

                            if(paramarray2.size() == 2)
                            {
                                int sState = 0;
                                if(paramarray1[0].ToInt(&sState))
                                    tmpSwitchRoutes[pSwitchNode][(SwitchState)sState] = tagSwitchRoute(paramarray2[0],paramarray2[1]);
                            }
                        }
                    }

                    pSwitchNode->setDeviceID(deviceid != NULL ? cJSON_GetNumberValue(deviceid) : this->getAllNodes().size());
                }
            }
                break;
            default:
                break;
            }
        }
    }

    // 获取所有的挂载点
    cJSON *mountpoints = cJSON_GetObjectItemCaseSensitive(root, "mountpoints");
    if (mountpoints && cJSON_IsArray(mountpoints)) {
        cJSON *mount_item = NULL;
        cJSON_ArrayForEach(mount_item, mountpoints) {
            cJSON *nodenameval = cJSON_GetObjectItemCaseSensitive(mount_item, "nodename");
            if (!nodenameval) {
                continue;
            }

            WBaseNode *psrcBaseNode = this->getNodeByName(wxString(cJSON_GetStringValue(nodenameval)));
            if (psrcBaseNode != NULL) {
                // 得到这个结点的所有挂载点
                cJSON *mounts = cJSON_GetObjectItemCaseSensitive(mount_item, "mounts");
                if (mounts && cJSON_IsArray(mounts)) {
                    cJSON *mount_val = NULL;
                    cJSON_ArrayForEach(mount_val, mounts) {
                        cJSON *mountnameval = cJSON_GetObjectItemCaseSensitive(mount_val, "mountname");
                        cJSON *mountnodeval = cJSON_GetObjectItemCaseSensitive(mount_val, "mountnode");
                        cJSON *levelval = cJSON_GetObjectItemCaseSensitive(mount_val, "level");
                        cJSON *orientationval = cJSON_GetObjectItemCaseSensitive(mount_val, "orientation");
                        cJSON *mountposval = cJSON_GetObjectItemCaseSensitive(mount_val, "mountpos");

                        if (!mountnameval || !mountnodeval || !levelval || !orientationval || !mountposval) {
                            continue;  // 跳过无效的挂载点
                        }

                        WBaseNode *pMountBaseNode = this->getNodeByName(wxString(cJSON_GetStringValue(mountnodeval)));
                        if (pMountBaseNode != NULL) {
                            cJSON *mountposXval = cJSON_GetObjectItemCaseSensitive(mountposval, "x");
                            cJSON *mountposYval = cJSON_GetObjectItemCaseSensitive(mountposval, "y");

                            if (!mountposXval || !mountposYval) {
                                continue;  // 跳过无效的位置数据
                            }

                            wxString pmountname = wxString(cJSON_GetStringValue(mountnameval),gb2312Conv);
                            int level = (int)cJSON_GetNumberValue(levelval);
                            MountDirection orientation = (MountDirection)static_cast<int>(cJSON_GetNumberValue(orientationval));
                            wxRealPoint pmountpos = wxRealPoint(
                                cJSON_GetNumberValue(mountposXval),
                                cJSON_GetNumberValue(mountposYval)
                            );

                            psrcBaseNode->addMountPoint(
                                pmountname,
                                tagMountPoint(pmountname,
                                              pmountpos,
                                              pMountBaseNode,
                                              level,
                                              orientation)
                            );
                        }
                    }
                }
            }
        }
    }

    // 获取所有的区段
    cJSON *sects = cJSON_GetObjectItemCaseSensitive(root, "sects");
    if (sects && cJSON_IsArray(sects)) {
        cJSON *sect_item = NULL;
        cJSON_ArrayForEach(sect_item, sects) {
            cJSON *sectnameval = cJSON_GetObjectItemCaseSensitive(sect_item, "sectname");
            if (!sectnameval) {
                continue;
            }

            tagSectNode *decSectNode = new tagSectNode();
            decSectNode->sectname = wxString(cJSON_GetStringValue(sectnameval));

            cJSON *rangeval = cJSON_GetObjectItemCaseSensitive(sect_item, "range");

            wxArrayString paramarray1 = SplitString(wxString(cJSON_GetStringValue(rangeval),gb2312Conv),";");
            if(!paramarray1.empty())
            {
                std::map<int,wxVector<WBaseNode*>> decSectNodeParams;

                for(int k=0;k<paramarray1.size();k++)
                {
                    wxArrayString paramarray2 = SplitString(paramarray1[k],"-");
                    if(paramarray2.size() == 2)
                    {
                        wxVector<tagSLRouteNode> decroute = this->getRoute(paramarray2[0],paramarray2[1]);

                        for(int ii=0;ii<decroute.size();ii++)
                        {
                            decSectNodeParams[k].push_back(decroute[ii].node);
                        }
                    }
                }

                decSectNode->nodes = decSectNodeParams;
            }

            cJSON *deviceidval = cJSON_GetObjectItemCaseSensitive(sect_item, "deviceid");
            decSectNode->deviceID = (deviceidval != NULL ? cJSON_GetNumberValue(deviceidval) : -1);

            cJSON *lastsectval = cJSON_GetObjectItemCaseSensitive(sect_item, "lastsect");
            decSectNode->lastsects = SplitString(wxString(cJSON_GetStringValue(lastsectval)),";");
            cJSON *nextsectval = cJSON_GetObjectItemCaseSensitive(sect_item, "nextsect");
            decSectNode->nextsects = SplitString(wxString(cJSON_GetStringValue(nextsectval)),";");

            cJSON *accessruleval = cJSON_GetObjectItemCaseSensitive(sect_item, "accessrule");
            decSectNode->accessrule = (accessruleval != NULL ? (SectAccessRule)cJSON_GetNumberValue(accessruleval) : SectAccessRule::ACCESS_NULL);

            std::lock_guard<std::mutex> lock(m_SectMutex);
            mSects[decSectNode->sectname] = decSectNode;
        }
    }

    // 获取所有的进路条件
    cJSON *routecondi = cJSON_GetObjectItemCaseSensitive(root, "routecondi");
    if (routecondi && cJSON_IsArray(routecondi)) {
        CRouteConditions::getSingleton().parsingJson(routecondi);
    }

    // 获取所有的GUI配置条件
    cJSON *guis = cJSON_GetObjectItemCaseSensitive(root, "guis");
    if (guis && cJSON_IsArray(guis)) {
        GuiManager::getSingleton().parsingJson(guis);
    }

    // 释放 JSON 文档
    cJSON_Delete(doc);

    // 最后删除不需要的脚本文件
    DeleteAllFilesInDir(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/resources/scripts/nodes",
                        decfiles);

    // 计算所有挂载点的角度
    computerStationNodeMountAngles();

    // 设置道岔的内部进路
    std::map<WBaseNode*,std::map<SwitchState,tagSwitchRoute>>::iterator iterswitch = tmpSwitchRoutes.begin();
    for(;iterswitch != tmpSwitchRoutes.end();++iterswitch)
    {
        WSwitchNode* pSwitchNode = static_cast<WSwitchNode*>((*iterswitch).first);
        if(pSwitchNode)
        {
            std::map<SwitchState,tagSwitchRoute>::iterator iterswitch2 = (*iterswitch).second.begin();
            for(;iterswitch2 != (*iterswitch).second.end();++iterswitch2)
            {
                pSwitchNode->initSwitchState((*iterswitch2).first,
                                            (*iterswitch2).second.startPos,
                                            (*iterswitch2).second.endPos);
            }
        }
    }

    /// 处理站场区段
    this->processStationSects();

    // 重新计算所有的股道
    LocoManager::getSingleton().changeWorkingRect();

    return true;
}

/// 设置结点的工作模式
void WNodeManager::setWorkingMode(WorkingMode mode)
{
    if(mNodes.empty()) return;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        (*iter).second->setWorkingMode(mode);
    }
}

/// 添加一个 信号灯
WSignalLampNode* WNodeManager::addSignalLamp(wxString nodeName,wxRealPoint pos)
{
    if(getNodeByName(nodeName) != NULL)
        return NULL;

    /*if((pos.x < 0 || pos.x > 100.0f) ||
       (pos.y < 0 || pos.y > 100.0f))
    {
        wxString perrString = wxString::Format("WNodeManager::addSignalLamp:%s:pos的值反正在0-100,"
                                               "不能超出这个范围:%f %f.",nodeName,pos.x,pos.y);
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,perrString);
        return NULL;
    }*/

    WSignalLampNode *pSignalLampNode = new WSignalLampNode(nodeName);
    pSignalLampNode->setNodeManager(this);
    pSignalLampNode->setPosition(pos);

    /// 建立脚本文件
    pSignalLampNode->createScriptFile();

    //std::lock_guard<std::mutex> lock(m_NodeMutex);
    mNodes[nodeName] = pSignalLampNode;

    return pSignalLampNode;
}

/// 添加一个道岔
WSwitchNode* WNodeManager::addSwitch(wxString nodeName,wxRealPoint pos)
{
    if(getNodeByName(nodeName) != NULL)
        return NULL;

    if((pos.x < 0 || pos.x > 100.0f) ||
       (pos.y < 0 || pos.y > 100.0f))
    {
        wxString perrString = wxString::Format(wxT("WNodeManager::addSwitch:%s:pos的值反正在0-100,"
                                                   "不能超出这个范围:%f %f."),nodeName,pos.x,pos.y);
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,perrString.ToUTF8().data());
        return NULL;
    }

    WSwitchNode *pSwitchNode = new WSwitchNode(nodeName);
    pSwitchNode->setNodeManager(this);
    pSwitchNode->setPosition(pos);

    /// 建立脚本文件
    pSwitchNode->createScriptFile();

    //std::lock_guard<std::mutex> lock(m_NodeMutex);
    mNodes[nodeName] = pSwitchNode;

    return pSwitchNode;
}

/// 添加一个挂接点
WMountNode* WNodeManager::addMountNode(wxString nodeName,wxRealPoint pos)
{
    if(getNodeByName(nodeName) != NULL)
        return NULL;

    if((pos.x < 0 || pos.x > 100.0f) ||
       (pos.y < 0 || pos.y > 100.0f))
    {
        wxString perrString = wxString::Format(wxT("WNodeManager::addMountNode:%s:pos的值反正在0-100,"
                                                   "不能超出这个范围:%f %f."),nodeName,pos.x,pos.y);
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,perrString.ToUTF8().data());
        return NULL;
    }

    WMountNode *pMountNode = new WMountNode(nodeName);
    pMountNode->setNodeManager(this);
    pMountNode->setPosition(pos);

    //std::lock_guard<std::mutex> lock(m_NodeMutex);
    mNodes[nodeName] = pMountNode;

    return pMountNode;
}

/// 得到指定坐标的结点
WBaseNode* WNodeManager::getNodeByPoint(wxPoint point)
{
    if(mNodes.empty()) return NULL;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        if((*iter).second->getBoundingRect().containsPoint(point))
            return (*iter).second;
    }

    return NULL;
}

/// 删除指定名称的结点
bool WNodeManager::deleteNodeByName(wxString nodeName)
{
    if(nodeName == "" || mNodes.empty())
        return false;

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.find(nodeName);
    if(iter == mNodes.end())
        return false;

    // 清除与之关联的挂结点
    std::map<wxString,WBaseNode*>::iterator iter2 = mNodes.begin();
    for(;iter2 != mNodes.end();++iter2)
    {
        (*iter2).second->deleteMountPointByNode((*iter).second);
    }

    delete (*iter).second;
    (*iter).second = NULL;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);
    mNodes.erase(iter);

    return true;
}

/// 删除与关联结点有关的挂载点
bool WNodeManager::deleteMountPointByNode(WBaseNode* node)
{
    if(node == NULL || mNodes.empty())
        return false;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    // 清除与之关联的挂结点
    std::map<wxString,WBaseNode*>::iterator iter2 = mNodes.begin();
    for(;iter2 != mNodes.end();++iter2)
    {
        if((*iter2).second != node)
            (*iter2).second->deleteMountPointByNode(node);
    }
}

/// 得到指定名称的结点
WBaseNode* WNodeManager::getNodeByName(wxString nodeName)
{
    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.find(nodeName);
    if(iter == mNodes.end())
        return NULL;

    return (*iter).second;
}

/// 得到指定设备ID的结点
WBaseNode* WNodeManager::getNodeByDeviceID(int deviceid)
{
    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        if((*iter).second->getDeviceID() == deviceid)
            return (*iter).second;
    }

    return NULL;
}

/// 清除所有的数据
void WNodeManager::clear(void)
{
    // 先删除所有的结点
    this->deleteAllNodes();
}

/// 删除所有的结点
void WNodeManager::deleteAllNodes(void)
{
    {
        //std::lock_guard<std::mutex> lock(m_NodeMutex);
        std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
        for(;iter != mNodes.end();++iter)
        {
            delete (*iter).second;
            (*iter).second = NULL;
        }
    }

    {
        //std::lock_guard<std::mutex> lock(m_RouteMutex);
        std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter2 = mRoutes.begin();
        for(;iter2 != mRoutes.end();++iter2)
        {
            std::map<wxString,tagRoute*>::iterator iter3 = (*iter2).second.begin();
            for(;iter3 != (*iter2).second.end();++iter3)
            {
                delete (*iter3).second;
                (*iter3).second = NULL;
            }
        }
    }

    {
        std::lock_guard<std::mutex> lock(m_SectMutex);
        std::map<wxString,tagSectNode*>::iterator itersect = mSects.begin();
        for(;itersect != mSects.end();++itersect)
        {
            delete (*itersect).second;
            (*itersect).second = NULL;
        }
    }

    mNodes.clear();
    mSects.clear();
    mRoutes.clear();
    mdecSectNodes.clear();
    m_TimerItems.clear();
}

/// 工作区域改变
void WNodeManager::changeWorkingRect(wxRect workingrect)
{
    if(mWorkingRect == workingrect) return;

    mWorkingRect = workingrect;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
        (*iter).second->changeWorkingRect(workingrect);

    // 计算所有挂载点的角度
    computerStationNodeMountAngles();
}

/// 计算站场指定结点挂载点的角度
void WNodeManager::computerNodeMountAngles(WBaseNode* basenode)
{
    if(basenode == NULL ||
        basenode->getNodeType() != NODE_SIGNAL)
        return;

    // 右边的连接点
    wxVector<tagMountPoint> pRightPoints = basenode->getMountPointByDir(DIRECTION_RIGHT);
    if(!pRightPoints.empty())
    {
        for(int i=0;i<pRightPoints.size();i++)
        {
            // 得到对应点的左边结点
            WBaseNode *pLeftNode = pRightPoints[i].node;

            tagMountPoint point;

            // 检测右边结点是否有挂接左边结点
            if(pLeftNode &&
                pLeftNode->isExistMountNode(basenode,DIRECTION_LEFT,&point))
            {
                wxRealPoint rightpos = pRightPoints[i].screenpos;
                wxRealPoint leftpos = point.screenpos;

                //pRightPoints[i].angle = CalculateAngle(rightpos,leftpos);
                basenode->setMountPointAngle(pRightPoints[i].name,
                                                   CalculateAngle(leftpos,rightpos));
            }
        }
    }

    // 左边的连接点
    wxVector<tagMountPoint> pLeftPoints = basenode->getMountPointByDir(DIRECTION_LEFT);
    if(!pLeftPoints.empty())
    {
        for(int i=0;i<pLeftPoints.size();i++)
        {
            // 得到对应点的右边结点
            WBaseNode *pRightNode = pLeftPoints[i].node;

            tagMountPoint point;

            // 检测右边结点是否有挂接左边结点
            if(pRightNode &&
                pRightNode->isExistMountNode(basenode,DIRECTION_RIGHT,&point))
            {
                wxRealPoint leftpos = pLeftPoints[i].screenpos;
                wxRealPoint rightpos = point.screenpos;

                //pLeftPoints[i].angle = CalculateAngle(leftpos,rightpos);
                basenode->setMountPointAngle(pLeftPoints[i].name,
                                                   CalculateAngle(leftpos,rightpos));
            }
        }
    }
}

/// 计算站场所有结点挂载点的角度
void WNodeManager::computerStationNodeMountAngles(void)
{
    if(mNodes.empty()) return;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        if((*iter).second->getNodeType() != NODE_SIGNAL)
            continue;

        computerNodeMountAngles((*iter).second);
    }
}

/// 得到区段的名称
wxString WNodeManager::getSectName(WBaseNode* startNode,WBaseNode* endNode)
{
    //std::lock_guard<std::mutex> lock(m_DecSectMutex);
    for (const auto& [sectName, sectNode] : mdecSectNodes) {
        for (const auto& [id, nodes] : sectNode.nodes) {
            bool hasStart = std::find(nodes.begin(), nodes.end(), startNode) != nodes.end();
            bool hasEnd = std::find(nodes.begin(), nodes.end(), endNode) != nodes.end();

            if (hasStart && hasEnd) {
                return sectName;  // Return immediately on first match
            }
        }
    }

    return wxString("");  // Explicit empty wxString
}

/// 得到区段的颜色
wxColour WNodeManager::getSectColor(WBaseNode* startNode,WBaseNode* endNode)
{
    wxColour color(255,255,255,255);

    //std::lock_guard<std::mutex> lock(m_DecSectMutex);
    std::map<wxString,tagSectNode>::iterator iter = mdecSectNodes.begin();
    for(;iter != mdecSectNodes.end();++iter)
    {
        std::map<int,wxVector<WBaseNode*>>::iterator iter2 = (*iter).second.nodes.begin();
        for(;iter2 != (*iter).second.nodes.end();++iter2)
        {
            auto it = std::find((*iter2).second.begin(),
                                (*iter2).second.end(),
                                startNode);
            auto it1 = std::find((*iter2).second.begin(),
                                (*iter2).second.end(),
                                endNode);
            if (it != (*iter2).second.end() &&
                it1 != (*iter2).second.end())
            {
                return (*iter).second.getStateColor();
            }
        }
    }

    return color;
}

/// 设置指定区段的操作状态
void WNodeManager::setSectOperState(wxString sectName,int state)
{
    if(mSects.empty() || sectName == "")
        return;

    {
        //std::lock_guard<std::mutex> lock(m_SectMutex);
        std::map<wxString,tagSectNode*>::iterator iter = mSects.find(sectName);
        if(iter == mSects.end())
            return;

        (*iter).second->operstate = (NodeOperState)state;
    }

    this->slot_processSwitchChangeToSect();
}

/// 控制信号灯
bool WNodeManager::controlTheSignalLamp(wxString nodeName,bool isOpen,luabridge::LuaRef pcallback)
{
    WBaseNode* pBaseNode = this->getNodeByName(nodeName);
    if(pBaseNode == NULL || pBaseNode->getNodeType() != NodeType::NODE_SIGNAL)
        return false;

    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    // 检测这个灯是否在进路中
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter = mRoutes.find(pBaseNode->getName());
    if(iter == mRoutes.end())
        return false;

    if((isOpen && pBaseNode->getSignalState() == NodeSignalState::OCCUPY) ||
        (!isOpen && pBaseNode->getSignalState() == NodeSignalState::CLEAR))
        return false;

    this->sendSignal(wxString::Format(wxT("%s信号灯%s"),(isOpen ? wxT("打开") : wxT("关闭")),nodeName).utf8_string(),
                     wxString::Format(wxT("{\"signal\":{\"信号灯\":[{\"%d\":\"%s\"}]}}"),
                                      pBaseNode->getDeviceID(),
                                      (isOpen ? wxT("白灯") : wxT("蓝灯"))).ToUTF8().data(),
                     5,
                     pcallback);

    return true;
}

/// 发送信号到设备
bool WNodeManager::sendSignal(std::string opertype,std::string signalMsg,int interval,luabridge::LuaRef pcallback)
{
    if(signalMsg == "" || opertype == "")
        return false;

    wxString decsignalMsg = Converttargetstatementintooutputsignal(opertype,signalMsg);

    if(decsignalMsg == "")
    {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_WARN,"数据转换错误！");
        return false;
    }

    CMainFrame::getSingleton().printlog(7,
                                        wxString::Format(wxT("控制消息:%s"),decsignalMsg).utf8_string());

    wxScopedCharBuffer decSendMsg = decsignalMsg.ToUTF8();
    WTcpClient::getSingleton().SendData(IDD_NETWORK_MSG_SIGNAL_CONTROL,
                                           decSendMsg.data(),
                                           decSendMsg.length());

    mLockedScreen = true;
    this->startTimer(opertype.c_str(),interval,1,pcallback);

    return true;
}

/// 设置指定区段的信号状态
void WNodeManager::setSectSignalState(tagSectNode *pSectNode,int state)
{
    if(mSects.empty() || pSectNode == NULL)
        return;

    pSectNode->lastsignalstate = pSectNode->signalstate;
    pSectNode->signalstate = (NodeSignalState)state;

    this->slot_processSwitchChangeToSect();
}

/// 根据指定结点得到结点所在区段
tagSectNode* WNodeManager::getSectByNode(WBaseNode* node)
{
    if(node == NULL || mSects.empty()) return NULL;

    //std::lock_guard<std::mutex> lock(m_SectMutex);
    std::map<wxString,tagSectNode*>::iterator itersect = mSects.begin();
    for(;itersect != mSects.end();++itersect)
    {
        if((*itersect).second->isExistBaseNode(node))
            return (*itersect).second;
    }

    return NULL;
}

/// 处理道岔状态变化导致区段变化事件
void WNodeManager::slot_processSwitchChangeToSect(wxString switchName)
{
    wxString decSectName = "";

    tagSectNode* pSectNode = this->getSectByNode(this->getNodeByName(switchName));
    if(pSectNode != NULL)
        decSectName = pSectNode->sectname;

    /// 处理站场区段，得到区段占用情况
    this->processStationSects(decSectName);

    // 重新计算所有的股道
    LocoManager::getSingleton().changeWorkingRect(decSectName);
}

void WNodeManager::processStationSect(wxString sectName)
{
    if(mSects.empty() || sectName == "") return;

    //std::lock_guard<std::mutex> lock(m_SectMutex);
    std::map<wxString,tagSectNode*>::iterator iter = mSects.find(sectName);
    if(iter != mSects.end())
    {
        {
            //std::lock_guard<std::mutex> lock(m_DecSectMutex);
            mdecSectNodes[(*iter).first] = *((*iter).second);
        }

        // 处理道岔占用
        if((*iter).second->nodes.size() > 1)
        {
            bool isFinded = false;
            WBaseNode *pdecSwitch = NULL;
            std::map<int,wxVector<WBaseNode*>>::iterator iternode = (*iter).second->nodes.begin();
            for(;iternode != (*iter).second->nodes.end();++iternode)
            {
                for(int i=0;i<(*iternode).second.size();i++)
                {
                    if((*iternode).second[i]->getNodeType() == NodeType::NODE_SWITCH)
                    {
                        if(pdecSwitch != NULL && pdecSwitch == (*iternode).second[i])
                        {
                            WSwitchNode *pswitchnode = static_cast<WSwitchNode*>(pdecSwitch);
                            if(pswitchnode)
                            {
                                mdecSectNodes[(*iter).first].nodes.clear();
                                mdecSectNodes[(*iter).first].nodes[pswitchnode->getSwitchState()] = (*iter).second->nodes[pswitchnode->getSwitchState()];
                                mdecSectNodes[(*iter).first].curSwitchState = (SwitchState)pswitchnode->getSwitchState();
                                mSects[(*iter).first]->curSwitchState = (SwitchState)pswitchnode->getSwitchState();

                                // 设置区段中所有的道岔信号状态和区段一致
                                wxVector<WBaseNode*> decnodes = mdecSectNodes[(*iter).first].nodes[pswitchnode->getSwitchState()];
                                for(int k=0;k<decnodes.size();k++)
                                {
                                    if(decnodes[k]->getNodeType() == NodeType::NODE_SWITCH)
                                        decnodes[k]->setSignalState(mdecSectNodes[(*iter).first].signalstate);
                                }

                                isFinded = true;
                                break;
                            }
                        }

                        pdecSwitch = (*iternode).second[i];
                    }
                }

                if(isFinded)
                    break;
            }
        }
    }
}

/// 处理站场区段，得到区段占用情况
void WNodeManager::processStationSects(wxString sectName)
{
    if(mSects.empty()) return;

    {
        //std::lock_guard<std::mutex> lock(m_DecSectMutex);
        mdecSectNodes.clear();
    }

    if(sectName == "")
    {
        //std::lock_guard<std::mutex> lock(m_SectMutex);
        std::map<wxString,tagSectNode*>::iterator iter = mSects.begin();
        for(;iter != mSects.end();++iter)
        {
            this->processStationSect((*iter).first);
        }
    }
    else
    {
        this->processStationSect(sectName);
    }
}

/// 绘制站场结点之间的连接
void WNodeManager::drawStationNodeLinks(maindrawscene *painter)
{
    if(mNodes.empty()) return;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    for (const auto& [nodeName, node] : mNodes) {
        const auto pRightPoints = node->getMountPointByDir(DIRECTION_RIGHT);

        for (const auto& rightPoint : pRightPoints) {
            WBaseNode* pLeftNode = rightPoint.node;
            if (!pLeftNode) continue;

            tagMountPoint point;
            if (!pLeftNode->isExistMountNode(node, DIRECTION_LEFT, &point)) {
                continue;
            }

            const wxRealPoint& rightpos = rightPoint.screenpos;
            const wxRealPoint& leftpos = point.screenpos;

            double decAngle = CalculateAngle(rightpos, leftpos);
            decAngle = (decAngle > 0.0) ? (360.0 - decAngle) : 0.0;

            wxString decSectName = getSectName(point.node, rightPoint.node);

            // Draw connection line
            painter->DrawLine(leftpos, rightpos, 2.0f,
                              getSectColor(point.node, rightPoint.node));

            // Draw text label
            if (decSectName != "") {
                painter->DrawText1(decSectName.ToUTF8().data(),
                                   GetInterpolatedPoint(rightpos, leftpos, 0.5f),
                                   1.0f,
                                   wxColour(0, 255, 255, 255),
                                   decAngle);
            }
        }
    }
}

/// 搜索两个结点之间的进路
std::list<tagSLRouteNode> WNodeManager::searchRoute(WBaseNode* startNode,WBaseNode* endNode,MountDirection md)
{
    std::list<tagSLRouteNode> pBaseNodeList;

    pBaseNodeList.push_front(tagSLRouteNode(startNode,0));

    while(!pBaseNodeList.empty())
    {
        tagSLRouteNode tmpBaseNode = pBaseNodeList.front();
        pBaseNodeList.pop_front();

        wxVector<tagMountPoint> pMountPoints = tmpBaseNode.node->getMountPointByDir(md);
        if(pMountPoints.empty())
            continue;

        int tmpindex=tmpBaseNode.MPointIndex;

        if(tmpindex >= pMountPoints.size())
            continue;

        tmpBaseNode.MPointIndex+=1;
        pBaseNodeList.push_front(tmpBaseNode);

        if(pMountPoints[tmpindex].node != endNode)
        {
            pBaseNodeList.push_front(tagSLRouteNode(pMountPoints[tmpindex].node,0));
        }
        else
        {
            pBaseNodeList.push_front(tagSLRouteNode(pMountPoints[tmpindex].node,1));
            break;
        }
    }

    return pBaseNodeList;
}

/// 打印进路条件
void WNodeManager::printSect(const tagRouteCondiItem* routecondiitem)
{
    if(routecondiitem == NULL) return;

    wxString tmpStr = wxT(" 敌对信号灯:");
    for(int i=0;i<routecondiitem->conflictsignals.size();i++)
        tmpStr += wxString::Format(wxT("%s,"),routecondiitem->conflictsignals[i]->getName());
    wxString tmpStr2 = wxT(" 敌对道岔:");
    for(int i=0;i<routecondiitem->conflictswitch.size();i++)
        tmpStr2 += wxString::Format(wxT("%s:%d,"),routecondiitem->conflictswitch[i].switchnode->getName(),
                                    routecondiitem->conflictswitch[i].switchstate);
    wxString tmpStr3 = wxT(" 带动道岔:");
    for(int i=0;i<routecondiitem->followswitch.size();i++)
        tmpStr3 += wxString::Format(wxT("%s:%d,"),routecondiitem->followswitch[i].switchnode->getName(),
                                    routecondiitem->followswitch[i].switchstate);

    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                        wxString::Format(wxT("进路条件:%s-%s %s %s %s"),
                                                         routecondiitem->startLight,routecondiitem->endLight,
                                                         tmpStr,tmpStr2,tmpStr3).ToUTF8().data());
}

/// 检测两个结点之间进路的有效性
wxVector<tagRouteCondiItem*> WNodeManager::checkRoute(wxString startNode,wxString endNode)
{
    wxVector<tagRouteCondiItem*> resultCondiItems;

    wxVector<tagSLRouteNode> resultRouteNodes = this->getRoute(startNode,endNode,true);

    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>> tempRouteNodes;
    std::vector<tagSLRouteNode*> routenodearray;
    int lightCount = 0;

    for(int k=0;k<resultRouteNodes.size();k++)
    {
        routenodearray.push_back(&resultRouteNodes[k]);

        if(resultRouteNodes[k].node->getNodeType() == NodeType::NODE_SIGNAL &&
            !routenodearray.empty())
        {
            lightCount+=1;

            if(lightCount >= 2)
            {
                tempRouteNodes[routenodearray[0]][routenodearray[routenodearray.size()-1]] = routenodearray;

                WSignalLampNode *pSignalLampNode = static_cast<WSignalLampNode*>(routenodearray[routenodearray.size()-1]->node);
                if((pSignalLampNode != NULL &&
                     (pSignalLampNode->getRouteType() == SLRouteType::ROUTE_LEFT || pSignalLampNode->getRouteType() == SLRouteType::ROUTE_RIGHT)) &&
                    k+1 < resultRouteNodes.size() &&
                    resultRouteNodes[k+1].node->getNodeType() == NodeType::NODE_SIGNAL)
                {
                    std::vector<tagSLRouteNode*> routenodearray2;
                    routenodearray2.push_back(routenodearray[routenodearray.size()-1]);
                    routenodearray2.push_back(&resultRouteNodes[k+1]);

                    tempRouteNodes[routenodearray2[0]][routenodearray2[1]] = routenodearray2;
                }

                routenodearray.clear();
                lightCount = 0;
            }
        }
    }

    wxString decRouteList = wxT("进路列表:");
    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>>::iterator iterroute = tempRouteNodes.begin();
    for(;iterroute != tempRouteNodes.end();++iterroute)
    {
        std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>::iterator iterroute2 = (*iterroute).second.begin();
        for(;iterroute2 != (*iterroute).second.end();++iterroute2)
        {
            decRouteList += wxString::Format(wxT("%s-%s;"),(*iterroute).first->node->getName(),(*iterroute2).first->node->getName());
            tagRouteCondiItem* pRouteCondiItem = CRouteConditions::getSingleton().getRouteCondiItem((*iterroute).first->node->getName(),
                                                                                                    (*iterroute2).first->node->getName());
            if(pRouteCondiItem != NULL)
                resultCondiItems.push_back(pRouteCondiItem);
        }
    }
    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,decRouteList.ToUTF8().data());

    return resultCondiItems;
}

/// 添加新的区段
bool WNodeManager::addSect(tagSectNode *newsect)
{
    if(newsect == NULL ||
        this->getSect(newsect->sectname) != NULL)
        return false;

    {
        std::lock_guard<std::mutex> lock(m_SectMutex);
        mSects[newsect->sectname] = newsect;
    }

    this->slot_processSwitchChangeToSect();

    return true;
}

/// 更改区段的名称
bool WNodeManager::updateSectByName(wxString oldsectName,wxString newsectName)
{
    if(oldsectName == "" || newsectName == "")
        return false;

    tagSectNode *oldSectNode = this->getSect(oldsectName);
    tagSectNode *newSectNode = this->getSect(newsectName);

    if(oldSectNode == NULL || newSectNode != NULL ||
       oldSectNode == newSectNode)
        return false;

    memcpy(newSectNode,oldSectNode,sizeof(tagSectNode));

    {
        std::lock_guard<std::mutex> lock(m_SectMutex);
        mSects[newsectName] = newSectNode;

        std::map<wxString,tagSectNode*>::iterator iter = mSects.find(oldsectName);
        if(iter != mSects.end())
        {
            delete (*iter).second;
            mSects.erase(iter);
        }
    }

    this->slot_processSwitchChangeToSect();

    return true;
}

/// 设置鼠标光标
void WNodeManager::setMouseCursor(int cursorid)
{
    wxSetCursor((wxStockCursor)cursorid);  // 改变整个应用程序的光标
    wxYield();                   // 立即更新显示
}

/// 根据设备ID得到区段名称
wxString WNodeManager::getSectNameByDeviceID(int deviceid)
{
    tagSectNode *pSectNode = this->getSectByDeviceID(deviceid);
    if(pSectNode == NULL)
        return "";

    return pSectNode->sectname;
}

/// 删除指定名称的区段
bool WNodeManager::deleteSectByName(wxString sectName)
{
    if(sectName == "" || mSects.empty())
        return false;

    //std::lock_guard<std::mutex> lock(m_SectMutex);
    std::map<wxString,tagSectNode*>::iterator iter = mSects.find(sectName);
    if(iter != mSects.end())
    {
        mSects.erase(iter);

        this->slot_processSwitchChangeToSect();

        return true;
    }

    return false;
}

/// 得到指定设备ID的区段
tagSectNode* WNodeManager::getSectByDeviceID(int deviceid)
{
    if(deviceid <= 0 || mSects.empty())
        return NULL;

    //std::lock_guard<std::mutex> lock(m_SectMutex);
    std::map<wxString,tagSectNode*>::iterator iter = mSects.begin();
    for(;iter != mSects.end();++iter)
    {
        if((*iter).second->deviceID == deviceid)
            return (*iter).second;
    }

    return NULL;
}

/// 得到指定名称的区段
tagSectNode* WNodeManager::getSect(wxString sectName)
{
    if(sectName == "" || mSects.empty())
        return NULL;

    //std::lock_guard<std::mutex> lock(m_SectMutex);
    std::map<wxString,tagSectNode*>::iterator iter = mSects.find(sectName);
    if(iter == mSects.end())
        return NULL;

    return (*iter).second;
}

/// 得到指定的进路
tagRoute* WNodeManager::getSelectedRoute(wxString startLight,wxString endLight)
{
    if(startLight == "" || endLight == "")
        return NULL;

    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter = mRoutes.find(startLight);
    if(iter != mRoutes.end())
    {
        std::map<wxString,tagRoute*>::iterator iter2 = (*iter).second.find(endLight);
        if(iter2 != (*iter).second.end())
            return (*iter2).second;
    }

    return NULL;
}

/// 取消开始信号灯的指定进路
bool WNodeManager::cancelRoute(wxString startNode,luabridge::LuaRef pcallback)
{
    WBaseNode *pBaseNode = this->getNodeByName(startNode);
    if(pBaseNode == NULL || pBaseNode->getNodeType() != NodeType::NODE_SIGNAL)
        return false;

    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    // 检测是否在工作进路中
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iterroute = mRoutes.find(startNode);
    if(iterroute == mRoutes.end())
        return false;

    // 检测它所在进路区段是否处于占用状态
    std::map<wxString,tagRoute*>::iterator iterroute2 = (*iterroute).second.begin();
    for(;iterroute2 != (*iterroute).second.end();++iterroute2)
    {
        std::unordered_map<wxString,wxVector<tagSLRouteNode>> allroutesects = (*iterroute2).second->sectNodes;
        std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iterroutesect = allroutesects.begin();
        for(;iterroutesect != allroutesects.end();++iterroutesect)
        {
            tagSectNode* pSectNode = this->getSect((*iterroutesect).first);
            if(pSectNode != NULL && pSectNode->signalstate == NodeSignalState::OCCUPY)
                return false;
        }
    }

    // 如果开始灯是打开状态，关闭它
    if(pBaseNode->getSignalState() == NodeSignalState::OCCUPY)
    {
        this->sendSignal(wxString::Format(wxT("取消开始进路%s"),pBaseNode->getName()).utf8_string(),
                             wxString::Format(wxT("{\"signal\":{\"信号灯\":[{\"%d\":\"蓝灯\"}]}}"),pBaseNode->getDeviceID()).ToUTF8().data(),
                         5,
                         pcallback);
    }
    else
    {
        this->deleteRoute(startNode);
        return true;
    }

    return false;
}

/// 删除开始信号灯的指定进路
bool WNodeManager::deleteRoute(wxString startNode)
{
    WBaseNode *pBaseNode = this->getNodeByName(startNode);
    if(pBaseNode == NULL || pBaseNode->getNodeType() != NodeType::NODE_SIGNAL)
        return false;

    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    // 检测是否在工作进路中
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iterroute = mRoutes.find(startNode);
    if(iterroute == mRoutes.end())
        return false;

    // 检测它所在进路区段是否处于占用状态
    std::map<wxString,tagRoute*>::iterator iterroute2 = (*iterroute).second.begin();
    for(;iterroute2 != (*iterroute).second.end();++iterroute2)
    {
        std::unordered_map<wxString,wxVector<tagSLRouteNode>> allroutesects = (*iterroute2).second->sectNodes;
        std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iterroutesect = allroutesects.begin();
        for(;iterroutesect != allroutesects.end();++iterroutesect)
        {
            tagSectNode* pSectNode = this->getSect((*iterroutesect).first);
            if(pSectNode != NULL && pSectNode->signalstate == NodeSignalState::OCCUPY)
                return false;
        }
    }

    // 如果开始灯是打开状态，关闭它
    if(pBaseNode->getSignalState() == NodeSignalState::OCCUPY)
    {
        /*this->sendSignal(wxString::Format(wxT("关闭信号灯%s"),pBaseNode->getName()).ToUTF8().data(),
                         wxString::Format(wxT("{\"signal\":{\"信号灯\":[{\"%d\":\"蓝灯\"}]}}"),pBaseNode->getDeviceID()).ToUTF8().data(),
                         5,
                         ScriptManager::getSingleton().createEmptyCallback());*/
        pBaseNode->setOperState(NodeOperState::NORMAL);
    }

    // 所有区段全部解锁
    iterroute2 = (*iterroute).second.begin();
    for(;iterroute2 != (*iterroute).second.end();++iterroute2)
    {
        std::unordered_map<wxString,wxVector<tagSLRouteNode>> allroutesects = (*iterroute2).second->sectNodes;
        std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iterroutesect = allroutesects.begin();
        for(;iterroutesect != allroutesects.end();++iterroutesect)
        {
            tagSectNode* pSectNode = this->getSect((*iterroutesect).first);
            if(pSectNode != NULL)
            {
                pSectNode->clearLock();
                pSectNode->lastsignalstate = NodeSignalState::CLEAR;
            }
        }
    }

    // 删除这条进路
    iterroute2 = (*iterroute).second.begin();
    for(;iterroute2 != (*iterroute).second.end();++iterroute2)
    {               
        delete (*iterroute2).second;
        (*iterroute2).second = NULL;
    }

    mRoutes.erase(iterroute);

    return true;
}

/// 添加一条进路到系统中
wxVector<tagRoute*> WNodeManager::addRoute(wxVector<tagSLRouteNode> resultRouteNodes)
{
    if(resultRouteNodes.empty())
        return wxVector<tagRoute*>();

    wxVector<tagRoute*> decRoutes;

    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>> tempRouteNodes;
    std::vector<tagSLRouteNode*> routenodearray;
    int lightCount = 0;

    for(int k=0;k<resultRouteNodes.size();k++)
    {
        routenodearray.push_back(&resultRouteNodes[k]);

        if(resultRouteNodes[k].node->getNodeType() == NodeType::NODE_SIGNAL &&
            !routenodearray.empty())
        {
            lightCount+=1;

            if(lightCount >= 2)
            {
                tagSLRouteNode* startnode = routenodearray[0];
                tagSLRouteNode* endnode =routenodearray[routenodearray.size()-1];

                WSignalLampNode *pSignalLampNode = static_cast<WSignalLampNode*>(routenodearray[routenodearray.size()-1]->node);
                if((pSignalLampNode != NULL &&
                     (pSignalLampNode->getRouteType() == SLRouteType::ROUTE_LEFT || pSignalLampNode->getRouteType() == SLRouteType::ROUTE_RIGHT)) &&
                    k+1 < resultRouteNodes.size() &&
                    resultRouteNodes[k+1].node->getNodeType() == NodeType::NODE_SIGNAL)
                {
                    //routenodearray.push_back(&resultRouteNodes[k+1]);
                }

                tempRouteNodes[startnode][endnode] = routenodearray;

                routenodearray.clear();
                lightCount = 0;
            }
        }
    }

    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>>::iterator iterroute = tempRouteNodes.begin();
    for(;iterroute != tempRouteNodes.end();++iterroute)
    {
        tagRoute *pRoute = new tagRoute();
        pRoute->startLight = (*iterroute).first->node->getName();

        std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>::iterator iterroute2 = (*iterroute).second.begin();
        for(;iterroute2 != (*iterroute).second.end();++iterroute2)
        {
            pRoute->endLight = (*iterroute2).first->node->getName();

            wxString tempStr = wxString::Format("%s:%s:",pRoute->startLight,pRoute->endLight);
            for(int i=0;i<(*iterroute2).second.size();i++)
            {
                pRoute->sectNodes[(*iterroute2).second[i]->sectName].push_back(*((*iterroute2).second[i]));

                tempStr += wxString::Format("%s:%s,",(*iterroute2).second[i]->node->getName(),(*iterroute2).second[i]->sectName);
            }
            CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,tempStr.ToUTF8().data());

            {
                //std::lock_guard<std::mutex> lock(m_RouteMutex);
                if(mRoutes[pRoute->startLight][pRoute->endLight] != NULL)
                    this->deleteRoute(pRoute->startLight);

                mRoutes[pRoute->startLight][pRoute->endLight] = pRoute;

                decRoutes.push_back(mRoutes[pRoute->startLight][pRoute->endLight]);
            }
        }
    }

    return decRoutes;
}

/// 关闭进路中指定区段的信号灯
wxString WNodeManager::closeRouteAllLights(wxString sectName)
{
    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter = mRoutes.begin();
    for(;iter != mRoutes.end();++iter)
    {
        std::map<wxString,tagRoute*>::iterator iter2 = (*iter).second.begin();
        for(;iter2 != (*iter).second.end();++iter2)
        {
            wxString sendMsg = (*iter2).second->closeAllLights(sectName);
            if(sendMsg != "")
                return sendMsg;
        }
    }

    return "";
}

/// 自动清除进行中的进路
void WNodeManager::autoDeleteSelectedRoute(void)
{
    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter = mRoutes.begin();
    for(;iter != mRoutes.end();)
    {
        std::map<wxString,tagRoute*>::iterator iter2 = (*iter).second.begin();
        for(;iter2 != (*iter).second.end();)
        {
            int tmpSectCount = 0;
            int tmpclearsignalcount = 0;
            for(int i=0;i<(*iter2).second->getAllSects().size();i++)
            {
                tagSectNode *pSect = this->getSect((*iter2).second->getAllSects()[i]);
                if(pSect != NULL)
                {
                    if(pSect->signalstate == NodeSignalState::CLEAR && pSect->lastsignalstate == NodeSignalState::OCCUPY)
                    {
                        tmpSectCount+=1;
                    }

                    if(pSect->clearsignalcount > 1)
                        tmpclearsignalcount+=1;
                }
            }

            // 如果所有区段全部存在压过并解锁，而且存在信号反复变化，就解锁这个区段
            if(tmpSectCount == (*iter2).second->getAllSects().size() && tmpclearsignalcount > 0)
            {
                for(int i=0;i<(*iter2).second->getAllSects().size();i++)
                {
                    tagSectNode *pSect = this->getSect((*iter2).second->getAllSects()[i]);
                    if(pSect != NULL)
                    {
                        pSect->clearLock();
                        pSect->lastsignalstate = NodeSignalState::CLEAR;
                    }
                }

                delete (*iter2).second;
                (*iter2).second = NULL;

                iter2 = (*iter).second.erase(iter2);
            }
            else
                ++iter2;
        }

        if((*iter).second.empty())
            iter = mRoutes.erase(iter);
        else
            ++iter;
    }
}

/// 得到两个结点之间的进路
wxVector<tagSLRouteNode> WNodeManager::getRoute(wxString startNode,wxString endNode,bool isaddother)
{
    if((startNode == "" || endNode == "") || (startNode == endNode))
        return wxVector<tagSLRouteNode>();

    WBaseNode *pStartNode = this->getNodeByName(startNode);
    WBaseNode *pEndNode = this->getNodeByName(endNode);
    if(pStartNode == NULL || pEndNode == NULL)
        return wxVector<tagSLRouteNode>();

    bool isFinded = false;
    wxVector<tagSLRouteNode> resultRouteNodes;

    // 先从左往右搜索
    std::list<tagSLRouteNode> resultroutelist = this->searchRoute(pStartNode,
                                                                  pEndNode,
                                                                  DIRECTION_RIGHT);

    if(!resultroutelist.empty())
    {
        resultRouteNodes.assign(resultroutelist.rbegin(),resultroutelist.rend());
        isFinded = true;
    }

    if(!isFinded)
    {
        // 先从右往左搜索
        resultroutelist = this->searchRoute(pStartNode,
                                            pEndNode,
                                            DIRECTION_LEFT);

        if(!resultroutelist.empty())
            resultRouteNodes.assign(resultroutelist.rbegin(),resultroutelist.rend());
    }

    // 根据信号灯的设置选择是否带后面一条轨道
    if(isaddother && !resultRouteNodes.empty())
    {
        if(resultRouteNodes[resultRouteNodes.size()-1].node->getNodeType() == NodeType::NODE_SIGNAL)
        {
            WSignalLampNode *pWSignalLampNode = static_cast<WSignalLampNode*>(resultRouteNodes[resultRouteNodes.size()-1].node);
            if(pWSignalLampNode)
            {
                switch(pWSignalLampNode->getRouteType())
                {
                case SLRouteType::ROUTE_LEFT:
                {
                    if(!isFinded)
                    {
                        wxVector<tagMountPoint> pmountpoints = pWSignalLampNode->getMountPointByDir(MountDirection::DIRECTION_LEFT);
                        if(pmountpoints.size() == 1)
                           resultRouteNodes.push_back(tagSLRouteNode(pmountpoints[0].node,1));
                    }
                }
                    break;
                case SLRouteType::ROUTE_RIGHT:
                {
                    if(isFinded)
                    {
                        wxVector<tagMountPoint> pmountpoints = pWSignalLampNode->getMountPointByDir(MountDirection::DIRECTION_RIGHT);
                        if(pmountpoints.size() == 1)
                           resultRouteNodes.push_back(tagSLRouteNode(pmountpoints[0].node,1));
                    }
                }
                    break;
                default:
                    break;
                }
            }
        }
    }

    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>> tempRouteNodes;
    std::vector<tagSLRouteNode*> routenodearray;
    int lightCount = 0;

    for(int k=0;k<resultRouteNodes.size();k++)
    {
        routenodearray.push_back(&resultRouteNodes[k]);

        if(resultRouteNodes[k].node->getNodeType() == NodeType::NODE_SIGNAL &&
            !routenodearray.empty())
        {
            lightCount+=1;

            if(lightCount >= 2)
            {
                tempRouteNodes[routenodearray[0]][routenodearray[routenodearray.size()-1]] = routenodearray;
                routenodearray[0]->isLighted = true;

                for(int index=0;index<routenodearray.size();index++)
                    routenodearray[index]->isLocked = true;

                WSignalLampNode *pSignalLampNode = static_cast<WSignalLampNode*>(routenodearray[routenodearray.size()-1]->node);
                if((pSignalLampNode != NULL &&
                     (pSignalLampNode->getRouteType() == SLRouteType::ROUTE_LEFT || pSignalLampNode->getRouteType() == SLRouteType::ROUTE_RIGHT)) &&
                    k+1 < resultRouteNodes.size() &&
                    resultRouteNodes[k+1].node->getNodeType() == NodeType::NODE_SIGNAL)
                {
                    std::vector<tagSLRouteNode*> routenodearray2;
                    routenodearray2.push_back(routenodearray[routenodearray.size()-1]);
                    routenodearray2.push_back(&resultRouteNodes[k+1]);
                    resultRouteNodes[k+1].isLocked = false;

                    tempRouteNodes[routenodearray2[0]][routenodearray2[1]] = routenodearray2;                   
                }

                routenodearray.clear();
                lightCount = 0;
            }
        }
    }

    std::map<tagSLRouteNode*,std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>>::iterator iterroute = tempRouteNodes.begin();
    for(;iterroute != tempRouteNodes.end();++iterroute)
    {
        std::map<tagSLRouteNode*,std::vector<tagSLRouteNode*>>::iterator iterroute2 = (*iterroute).second.begin();
        for(;iterroute2 != (*iterroute).second.end();++iterroute2)
        {
            int pStartPosition = 0;

            //std::lock_guard<std::mutex> lock(m_SectMutex);
            std::map<wxString,tagSectNode*>::iterator iterSect = mSects.begin();
            for(;iterSect != mSects.end();++iterSect)
            {
                std::vector<tagSLRouteNode*> decRouteNodes = (*iterroute2).second;

                if(!isFinded)
                    std::reverse(decRouteNodes.begin(), decRouteNodes.end());

                int sectIndex = (*iterSect).second->isInSect(decRouteNodes,&pStartPosition);
                if(sectIndex >= 0 && pStartPosition > 0)
                {
                    for(int i=0;i<pStartPosition;i++)
                    {
                        (*iterroute2).second[i]->sectName = (*iterSect).first;
                        (*iterroute2).second[i]->sectPosition = sectIndex;
                    }
                }
            }
        }
    }

    return resultRouteNodes;
}

/// 处理鼠标事件
WBaseNode* WNodeManager::OnMMouseEvent(wxMouseEvent event)
{
    if(mNodes.empty() || mLockedScreen) return NULL;

   // std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        if((*iter).second->OnMMouseEvent(event))
            return (*iter).second;
    }

    return NULL;
}

/// 得到所有的进行中的进路
wxVector<tagRoute*> WNodeManager::getAllRoutes(void)
{
    wxVector<tagRoute*> decRoutes;

    //std::lock_guard<std::mutex> lock(m_RouteMutex);
    std::map<wxString,std::map<wxString,tagRoute*>>::iterator iter = mRoutes.begin();
    for(;iter != mRoutes.end();++iter)
    {
        std::map<wxString,tagRoute*>::iterator iter2 = (*iter).second.begin();
        for(;iter2 != (*iter).second.end();++iter2)
        {
            decRoutes.push_back((*iter2).second);
        }
    }

    return decRoutes;
}

/// 重置所有结点状态
void WNodeManager::resetAllNodes(void)
{
    if(mNodes.empty()) return;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
    {
        (*iter).second->reset();
    }
}

/// 绘制
void WNodeManager::draw(maindrawscene *painter)
{
    if(mNodes.empty()) return;

    //std::lock_guard<std::mutex> lock(m_NodeMutex);

    std::map<wxString,WBaseNode*>::iterator iter = mNodes.begin();
    for(;iter != mNodes.end();++iter)
        (*iter).second->draw(painter);

    /// 绘制站场结点之间的连接
    this->drawStationNodeLinks(painter);
}

/// 处理网络二进制消息
void WNodeManager::OnProcessNetData(WTcpClient* client,int msgType,wxMemoryBuffer& data)
{
    wxCSConv gb2312Conv(wxFONTENCODING_UTF8);

    //std::lock_guard<std::mutex> lock(*(maindrawscene::getSingleton().getSceneLock()));

    switch(msgType)
    {
    case IDD_NETWORK_MSG_SIGNAL_CONTROLRETURN: // 控制返回
    {
        if(data.GetDataLen() <= 0)
            return;

        wxString json_string = Convertinputsignalintotargetstatement2((const char*)data.GetData());

        CMainFrame::getSingleton().printlog(8,
                                            wxString::Format(wxT("[控制返回消息] %s"),json_string).ToUTF8().data());

        wxScopedCharBuffer decString = json_string.ToUTF8();

        // 解析JSON字符串
        cJSON *root = cJSON_Parse(decString.data());
        if (root != NULL)
        {
            // 解析区段信息
            cJSON *sect_json = cJSON_GetObjectItemCaseSensitive(root, "sect");
            if (sect_json != NULL && cJSON_IsArray(sect_json))
            {
                for (int i = 0; i < cJSON_GetArraySize(sect_json); i++)
                {
                    cJSON *setc_item = cJSON_GetArrayItem(sect_json, i);

                    cJSON *startlight = cJSON_GetObjectItem(setc_item, "startlight");
                    cJSON *endlight = cJSON_GetObjectItem(setc_item, "endlight");

                    if(startlight != NULL && endlight != NULL)
                    {
                        // 锁闭这条进路
                        tagRoute *pRoute = this->getSelectedRoute(wxString(startlight->valuestring,gb2312Conv),
                                                                  wxString(endlight->valuestring,gb2312Conv));
                        if(pRoute != NULL)
                        {
                            bool sectIsChanged = false;
                            std::unordered_map<wxString,wxVector<tagSLRouteNode>>::iterator iter = pRoute->sectNodes.begin();
                            for(;iter != pRoute->sectNodes.end();++iter)
                            {
                                // 锁闭区段
                                tagSectNode *pSectNode = this->getSect((*iter).first);
                                if(pSectNode)
                                {
                                    pSectNode->setSectOperState(NodeOperState::LOCKED);
                                    pSectNode->signalstate = NodeSignalState::CLEAR;
                                    pSectNode->lastsignalstate = NodeSignalState::CLEAR;
                                    pSectNode->clearsignalcount = 0;
                                    sectIsChanged = true;
                                }

                                // 锁闭区段中所有结点
                                for(int i=0;i<(*iter).second.size();i++)
                                {
                                    // 如果是最后一个信号灯，并且带后面一节轨道，就不锁闭后面那个灯了
                                    /*if((*iter).second[i].node->getNodeType() == NodeType::NODE_SIGNAL &&
                                        i+2 == (*iter).second.size())
                                    {
                                        WSignalLampNode *pSignalLampNode = static_cast<WSignalLampNode*>((*iter).second[i].node);
                                        if(pSignalLampNode &&
                                            (pSignalLampNode->getRouteType() == SLRouteType::ROUTE_LEFT || pSignalLampNode->getRouteType() == SLRouteType::ROUTE_RIGHT))
                                        {
                                            pSignalLampNode->setOperState(NodeOperState::LOCKED);
                                            break;
                                        }
                                    }*/

                                    if((*iter).second[i].isLocked)
                                        (*iter).second[i].node->setOperState(NodeOperState::LOCKED);
                                }
                            }

                            if(sectIsChanged) this->slot_processSwitchChangeToSect();
                        }
                    }
                }
            }

            bool isProcessMsgSuccessed = false;

            cJSON *signal = cJSON_GetObjectItem(root, "signal");
            if (signal != NULL)
            {
                // 解析道岔信息
                cJSON *switch_json = cJSON_GetObjectItemCaseSensitive(signal, "道岔");
                if (cJSON_IsArray(switch_json)) {
                    cJSON *switch_item = NULL;
                    cJSON_ArrayForEach(switch_item, switch_json)
                    {
                        cJSON *element = switch_item->child;
                        if (element)
                        {
                            WBaseNode *pBaseNode = this->getNodeByDeviceID(atoi(element->string));
                            if(pBaseNode == NULL)
                                pBaseNode = this->getNodeByName(wxString(element->string,gb2312Conv));

                            if(pBaseNode &&
                                pBaseNode->getNodeType() == NODE_SWITCH)
                            {
                                wxString decValue = wxString(element->valuestring,gb2312Conv);

                                pBaseNode->setSignalState(decValue == wxT("无信号") ?
                                                              NodeSignalState::NOSIGNAL : NodeSignalState::CLEAR);

                                if(decValue == wxT("定位") || decValue == wxT("反位"))
                                {
                                    WSwitchNode *pSwitchNode = static_cast<WSwitchNode*>(pBaseNode);
                                    if(pSwitchNode)
                                    {
                                        pSwitchNode->setSwitchState(decValue == wxT("定位") ?
                                                                        SwitchState::POSITIVE : SwitchState::NEGATIVE);
                                    }
                                }

                                isProcessMsgSuccessed = true;
                            }
                        }
                    }
                }

                // 解析信号灯信息
                cJSON *signal_json = cJSON_GetObjectItemCaseSensitive(signal, "信号灯");
                if (cJSON_IsArray(signal_json)) {
                    cJSON *signal_item = NULL;
                    cJSON_ArrayForEach(signal_item, signal_json)
                    {
                        cJSON *element = signal_item->child;
                        if (element)
                        {
                            WBaseNode *pBaseNode = this->getNodeByDeviceID(atoi(wxString(element->string,gb2312Conv)));
                            if(pBaseNode == NULL)
                                pBaseNode = this->getNodeByName(wxString(element->string,gb2312Conv));

                            if(pBaseNode &&
                                pBaseNode->getNodeType() == NODE_SIGNAL)
                            {
                                pBaseNode->setSignalState(wxString(element->valuestring,gb2312Conv) == wxT("白灯") ?
                                                              NodeSignalState::OCCUPY : NodeSignalState::CLEAR);

                                isProcessMsgSuccessed = true;
                            }
                        }
                    }
                }

                // 解析其它信号信息
                cJSON *othersignal_json = cJSON_GetObjectItemCaseSensitive(signal, "其它信号");
                if (cJSON_IsArray(othersignal_json)) {
                    cJSON *othersignal_item = NULL;
                    cJSON_ArrayForEach(othersignal_item, othersignal_json)
                    {
                        cJSON *element = othersignal_item->child;
                        if (element)
                        {
                            isProcessMsgSuccessed = true;
                        }
                    }
                }
            }

            // 关闭操作定时器
            cJSON *opertype_json = cJSON_GetObjectItemCaseSensitive(root, "opertype");
            if(opertype_json != NULL)
            {
                mLockedScreen = false;
                this->stopTimer(opertype_json->valuestring,isProcessMsgSuccessed);
            }

            // 释放内存
            cJSON_Delete(root);
        }

        // 调用脚本网络消息接口
        ScriptManager::getSingleton().callLuaFunctionWithNetworkMsg(msgType,decString.data());
    }
    break;
    case IDD_NETWORK_MSG_SIGNAL_COLLECT:       // 信号采集处理
    {
        if(data.GetDataLen() <= 0)
            return;

        wxString json_string = Convertinputsignalintotargetstatement((const char*)data.GetData());

        CMainFrame::getSingleton().printlog(9,
                                            wxString::Format(wxT("[信号采集] %s"),json_string).ToUTF8().data());

        wxScopedCharBuffer decString = json_string.ToUTF8();

        // 解析JSON字符串
        cJSON *root = cJSON_Parse(decString.data());
        if (root != NULL)
        {
            // 解析道岔信息
            cJSON *switch_json = cJSON_GetObjectItemCaseSensitive(root, "道岔");
            if (cJSON_IsArray(switch_json)) {
                cJSON *switch_item = NULL;
                cJSON_ArrayForEach(switch_item, switch_json)
                {
                    cJSON *element = switch_item->child;
                    if (element)
                    {
                        WBaseNode *pBaseNode = this->getNodeByDeviceID(atoi(element->string));
                        if(pBaseNode == NULL)
                            pBaseNode = this->getNodeByName(wxString(element->string,gb2312Conv));

                        if(pBaseNode &&
                            pBaseNode->getNodeType() == NODE_SWITCH)
                        {
                            wxString decValue = wxString(element->valuestring,gb2312Conv);

                            pBaseNode->setSignalState(decValue == wxT("无信号") ?
                                                          NodeSignalState::NOSIGNAL : NodeSignalState::CLEAR);

                            if(decValue == wxT("定位") || decValue == wxT("反位"))
                            {
                                WSwitchNode *pSwitchNode = static_cast<WSwitchNode*>(pBaseNode);
                                if(pSwitchNode)
                                {
                                    pSwitchNode->setSwitchState(decValue == wxT("定位") ?
                                                                    SwitchState::POSITIVE : SwitchState::NEGATIVE);
                                }
                            }
                        }
                    }
                }
            }

            // 解析信号灯信息
            cJSON *signal_json = cJSON_GetObjectItemCaseSensitive(root, "信号灯");
            if (cJSON_IsArray(signal_json)) {
                cJSON *signal_item = NULL;
                cJSON_ArrayForEach(signal_item, signal_json)
                {
                    cJSON *element = signal_item->child;
                    if (element)
                    {
                        WBaseNode *pBaseNode = this->getNodeByDeviceID(atoi(element->string));
                        if(pBaseNode == NULL)
                            pBaseNode = this->getNodeByName(wxString(element->string,gb2312Conv));

                        if(pBaseNode &&
                           pBaseNode->getNodeType() == NODE_SIGNAL)
                        {
                            pBaseNode->setSignalState(wxString(element->valuestring,gb2312Conv) == wxT("白灯") ?
                                                          NodeSignalState::OCCUPY : NodeSignalState::CLEAR);
                        }
                    }
                }
            }

            // 解析轨道区段信息
            cJSON *track_json = cJSON_GetObjectItemCaseSensitive(root, "轨道区段");
            if (cJSON_IsArray(track_json)) {
                cJSON *track_item = NULL;
                cJSON_ArrayForEach(track_item, track_json)
                {
                    cJSON *element = track_item->child;
                    if (element)
                    {
                        tagSectNode *pSectNode = this->getSectByDeviceID(atoi(element->string));
                        if(pSectNode == NULL)
                            pSectNode = this->getSect(wxString(element->string,gb2312Conv));

                        this->setSectSignalState(pSectNode,
                                                 wxString(element->valuestring,gb2312Conv) == wxT("占用") ?
                                                     NodeSignalState::OCCUPY : NodeSignalState::CLEAR);

                        // 信号变化累计
                        if(pSectNode->getSignalState() == NodeSignalState::CLEAR)
                            pSectNode->clearsignalcount+=1;
                    }
                }

                //this->slot_processSwitchChangeToSect();
            }

            // 释放内存
            cJSON_Delete(root);
        }

        // 调用脚本网络消息接口
        ScriptManager::getSingleton().callLuaFunctionWithNetworkMsg(msgType,decString.data());
    }
        break;
    default:
        break;
    }
}

/// 转换目标语句为输为信号
wxString WNodeManager::Converttargetstatementintooutputsignal(std::string opertype,std::string json_data)
{
    if(json_data == "" || opertype == "")
        return "";

    // 解析JSON字符串
    cJSON *root = cJSON_Parse(json_data.c_str());
    if (root == NULL) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,cJSON_GetErrorPtr());
        return "";
    }

    wxString sendSectString;
    wxString sendSignalString;

    cJSON *sect_json = cJSON_GetObjectItemCaseSensitive(root, "sect");
    if (sect_json != NULL && cJSON_IsArray(sect_json))
    {
        for (int i = 0; i < cJSON_GetArraySize(sect_json); i++)
        {
            cJSON *setc_item = cJSON_GetArrayItem(sect_json, i);

            cJSON *startlight = cJSON_GetObjectItem(setc_item, "startlight");
            cJSON *endlight = cJSON_GetObjectItem(setc_item, "endlight");

            if(startlight != NULL && endlight != NULL)
            {
                sendSectString += wxString::Format(wxT("{\"startlight\":\"%s\",\"endlight\":\"%s\"},"),
                                                   wxString::FromUTF8(startlight->valuestring),
                                                   wxString::FromUTF8(endlight->valuestring));
            }
        }
    }

    cJSON *signal = cJSON_GetObjectItemCaseSensitive(root, "signal");
    if (signal != NULL)
    {
        // 解析"道岔"数组
        cJSON *daocha = cJSON_GetObjectItemCaseSensitive(signal, "道岔");
        if (cJSON_IsArray(daocha)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, daocha) {
                cJSON *child = item->child;
                while (child) {
                    WBaseNode *pBaseNode = WNodeManager::getSingleton().getNodeByDeviceID(atoi(child->string));
                    if(pBaseNode != NULL) sendSignalString += wxString::Format("{\"%d\":%d},",pBaseNode->getDeviceID(),
                                                        wxString::FromUTF8(child->valuestring) == wxT("定位") ? NodeSignalState::CLEAR : NodeSignalState::OCCUPY);
                    child = child->next;
                }
            }
        }

        // 解析"信号灯"数组
        cJSON *signal_lights = cJSON_GetObjectItemCaseSensitive(signal, "信号灯");
        if (cJSON_IsArray(signal_lights)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, signal_lights) {
                cJSON *child = item->child;
                while (child) {
                    WBaseNode *pBaseNode = WNodeManager::getSingleton().getNodeByDeviceID(atoi(child->string));
                    if(pBaseNode != NULL) sendSignalString += wxString::Format("{\"%d\":%d},",pBaseNode->getDeviceID(),
                                                        wxString::FromUTF8(child->valuestring) == wxT("蓝灯") ? NodeSignalState::CLEAR : NodeSignalState::OCCUPY);
                    child = child->next;
                }
            }
        }

        // 解析"轨道区段"数组
        cJSON *track_sections = cJSON_GetObjectItemCaseSensitive(signal, "轨道区段");
        if (cJSON_IsArray(track_sections)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, track_sections) {
                cJSON *child = item->child;
                while (child) {
                    tagSectNode *pSectNode = WNodeManager::getSingleton().getSectByDeviceID(atoi(child->string));
                    if(pSectNode != NULL) sendSignalString += wxString::Format("{\"%d\":%d},",pSectNode->deviceID,
                                                        wxString::FromUTF8(child->valuestring) == wxT("出清") ? NodeSignalState::CLEAR : NodeSignalState::OCCUPY);
                    child = child->next;
                }
            }
        }

        // 解析"其它信号"数组
        cJSON *othersignal_sections = cJSON_GetObjectItemCaseSensitive(signal, "其它信号");
        if (cJSON_IsArray(othersignal_sections)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, othersignal_sections) {
                cJSON *child = item->child;
                while (child) {
                    sendSignalString += wxString::Format("{\"%s\":%d},",
                                                          wxString::FromUTF8(child->string),
                                                          wxString::FromUTF8(child->valuestring) == wxT("无电") ? NodeSignalState::CLEAR : NodeSignalState::OCCUPY);
                    child = child->next;
                }
            }
        }
    }

    if(sendSectString.length() > 0)
        sendSectString = sendSectString.Mid(0,sendSectString.length()-1);
    if(sendSignalString.length() > 0)
        sendSignalString = sendSignalString.Mid(0,sendSignalString.length()-1);

    // 释放内存
    cJSON_Delete(root);

    return wxString::Format(wxT("{\"opertype\":\"%s\",\"sect\":[%s],\"signal\":[%s]}"),
                            wxString::FromUTF8(opertype.c_str()),
                            sendSectString,
                            sendSignalString);
}

/// 转换输入信号为目标语句
wxString WNodeManager::Convertinputsignalintotargetstatement2(std::string json_data)
{
    if(json_data == "")
        return "";

    // 解析JSON字符串
    cJSON *root = cJSON_Parse(json_data.c_str());
    if (root == NULL) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,cJSON_GetErrorPtr());
        return "";
    }

    wxString switch_string,signal_string,sect_string;
    wxString sendSectString,sendOperTypeString,otherSignalString;

    cJSON *opertype_json = cJSON_GetObjectItemCaseSensitive(root, "opertype");
    if (opertype_json != NULL)
        sendOperTypeString = wxString::FromUTF8(opertype_json->valuestring);

    cJSON *sect_json = cJSON_GetObjectItemCaseSensitive(root, "sect");
    if (sect_json != NULL && cJSON_IsArray(sect_json))
    {
        for (int i = 0; i < cJSON_GetArraySize(sect_json); i++)
        {
            cJSON *setc_item = cJSON_GetArrayItem(sect_json, i);

            cJSON *startlight = cJSON_GetObjectItem(setc_item, "startlight");
            cJSON *endlight = cJSON_GetObjectItem(setc_item, "endlight");

            if(startlight != NULL && endlight != NULL)
            {
                sendSectString += wxString::Format(wxT("{\"startlight\":\"%s\",\"endlight\":\"%s\"},"),
                                                   wxString::FromUTF8(startlight->valuestring),
                                                   wxString::FromUTF8(endlight->valuestring));
            }
        }
    }

    cJSON *signal = cJSON_GetObjectItemCaseSensitive(root, "signal");
    if (signal != NULL)
    {
        // 遍历数组
        cJSON *item = NULL;
        cJSON_ArrayForEach(item, signal) {
            if (cJSON_IsObject(item)) {
                // 获取对象中的第一个键值对
                cJSON *child = item->child;
                int key = atoi(child->string);
                int value = child->valueint;

                bool isProcessMsgSuccessed = false;

                WBaseNode *pBaseNode = this->getNodeByDeviceID(key);
                if(pBaseNode != NULL)
                {
                    switch(pBaseNode->getNodeType())
                    {
                    case NodeType::NODE_SWITCH:
                    {
                        SwitchState decValue = (SwitchState)value;

                        wxString tmpStr = wxT("无信号");
                        if(decValue == SwitchState::POSITIVE) tmpStr = wxT("定位");
                        else if(decValue == SwitchState::NEGATIVE) tmpStr = wxT("反位");

                        switch_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);
                    }
                    break;
                    case NodeType::NODE_SIGNAL:
                    {
                        NodeSignalState decValue = (NodeSignalState)value;

                        wxString tmpStr = wxT("无信号");
                        if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("白灯");
                        else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("蓝灯");

                        signal_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);
                    }
                    break;
                    default:
                        break;
                    }

                    isProcessMsgSuccessed = true;
                }

                tagSectNode *pSectNode = this->getSectByDeviceID(key);
                if(pSectNode != NULL)
                {
                    NodeSignalState decValue = (NodeSignalState)value;

                    wxString tmpStr = wxT("无信号");
                    if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("占用");
                    else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("出清");

                    sect_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);

                    isProcessMsgSuccessed = true;
                }

                if(!isProcessMsgSuccessed)
                {
                    otherSignalString += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,(value == NodeSignalState::CLEAR ? wxT("无电") : wxT("有电")));
                }
            }
        }
    }

    // 释放内存
    cJSON_Delete(root);

    if(sendSectString.length() > 0)
        sendSectString = sendSectString.Mid(0,sendSectString.length()-1);
    if(switch_string.length() > 0)
        switch_string = switch_string.Mid(0,switch_string.length()-1);
    if(signal_string.length() > 0)
        signal_string = signal_string.Mid(0,signal_string.length()-1);
    if(sect_string.length() > 0)
        sect_string = sect_string.Mid(0,sect_string.length()-1);
    if(otherSignalString.length() > 0)
        otherSignalString = otherSignalString.Mid(0,otherSignalString.length()-1);

    return wxString::Format(wxT("{\"opertype\":\"%s\",\"sect\":[%s],\"signal\":{\"道岔\":[%s],\"信号灯\":[%s],\"轨道区段\":[%s],\"其它信号\":[%s]}}"),
                            sendOperTypeString,
                            sendSectString,
                            switch_string,signal_string,sect_string,otherSignalString);
}

wxString WNodeManager::Convertinputsignalintotargetstatement(std::string json_data)
{
    if(json_data == "")
        return "";

    // 解析JSON字符串
    cJSON *root = cJSON_Parse(json_data.c_str());
    if (root == NULL) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,cJSON_GetErrorPtr());
        return "";
    }

    wxString switch_string,signal_string,sect_string;

    // 遍历数组
    cJSON *item = NULL;
    cJSON_ArrayForEach(item, root) {
        if (cJSON_IsObject(item)) {
            // 获取对象中的第一个键值对
            cJSON *child = item->child;
            int key = atoi(child->string);
            int value = child->valueint;

            WBaseNode *pBaseNode = this->getNodeByDeviceID(key);
            if(pBaseNode != NULL)
            {
                switch(pBaseNode->getNodeType())
                {
                case NodeType::NODE_SWITCH:
                {
                    SwitchState decValue = (SwitchState)value;

                    wxString tmpStr = wxT("无信号");
                    if(decValue == SwitchState::POSITIVE) tmpStr = wxT("定位");
                    else if(decValue == SwitchState::NEGATIVE) tmpStr = wxT("反位");

                    switch_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);
                }
                break;
                case NodeType::NODE_SIGNAL:
                {
                    NodeSignalState decValue = (NodeSignalState)value;

                    wxString tmpStr = wxT("无信号");
                    if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("白灯");
                    else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("蓝灯");

                    signal_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);
                }
                break;
                default:
                    break;
                }
            }
            else
            {
                tagSectNode *pSectNode = this->getSectByDeviceID(key);
                if(pSectNode != NULL)
                {
                    NodeSignalState decValue = (NodeSignalState)value;

                    wxString tmpStr = wxT("无信号");
                    if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("占用");
                    else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("出清");

                    sect_string += wxString::Format(wxT("{\"%d\":\"%s\"},"),key,tmpStr);
                }
            }
        }
    }

    // 释放内存
    cJSON_Delete(root);

    if(switch_string.length() > 2)
        switch_string = switch_string.Mid(0,switch_string.length()-1);
    if(signal_string.length() > 2)
        signal_string = signal_string.Mid(0,signal_string.length()-1);
    if(sect_string.length() > 2)
        sect_string = sect_string.Mid(0,sect_string.length()-1);

    return wxString::Format(wxT("{\"道岔\":[%s],\"信号灯\":[%s],\"轨道区段\":[%s]}"),switch_string,signal_string,sect_string);
}

/// 开始定时器
void WNodeManager::startTimer(const char* name,int interval,
                            int runCount,luabridge::LuaRef pcallback)
{
    std::lock_guard<std::mutex> lock(m_TimerMutex);
    wxString decName = wxString::FromUTF8(name);

    m_TimerItems[decName] = tagTimerItem(decName,runCount,interval,pcallback);
}

/// 停止指定定时器
void WNodeManager::stopTimer(const char* name,bool state)
{
    std::lock_guard<std::mutex> lock(m_TimerMutex);
    wxString decName = wxString::FromUTF8(name);

    std::map<wxString,tagTimerItem>::iterator iter = m_TimerItems.find(decName);
    if(iter != m_TimerItems.end())
    {
        try {
            // 调用Lua函数
            if(!(*((*iter).second.callback)).isNil()) (*((*iter).second.callback))(name,state);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("WNodeManager::stopTimer: %s") , e.what()).utf8_string());
        }

        CMainFrame::getSingleton().printStatusBar(wxString::Format(wxT("%s操作完成."),(*iter).first));

        m_TimerItems.erase(iter);
    }
}

/// 停止所有定时器
void WNodeManager::stopAllTimer(void)
{
    std::lock_guard<std::mutex> lock(m_TimerMutex);

    m_TimerItems.clear();
}

/// 处理所有定时器事件
void WNodeManager::onProcessAllTimerEvent(void)
{
    if(m_TimerItems.empty())
        return;

    std::lock_guard<std::mutex> lock(m_TimerMutex);
    std::map<wxString,tagTimerItem>::iterator iter = m_TimerItems.begin();
    for(;iter != m_TimerItems.end();)
    {
        if((*iter).second.starttime++ < (*iter).second.interval)
        {
            CMainFrame::getSingleton().printStatusBar(wxString::Format(wxT("当前正在%s,还有%d秒可以操作，请稍后..."),
                                                                       (*iter).first,
                                                                       (*iter).second.interval-(*iter).second.starttime));

            ++iter;
            continue;
        }

        if((*iter).second.runCount != - 1 &&
            --(*iter).second.runCount <= 0)
        {
            try {
                // 调用Lua函数
                if(!(*((*iter).second.callback)).isNil()) (*((*iter).second.callback))((*iter).first.ToUTF8().data(),false);
            } catch (const luabridge::LuaException& e) {
                CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                    wxString::Format(wxT("WNodeManager::onProcessAllTimerEvent: %s") , e.what()).utf8_string());
            }

            CMainFrame::getSingleton().printStatusBar(wxString::Format(wxT("%s操作完成."),(*iter).first));

            iter = m_TimerItems.erase(iter);
            mLockedScreen = false;
            continue;
        }

        try {
            // 调用Lua函数
            if(!(*((*iter).second.callback)).isNil()) (*((*iter).second.callback))((*iter).first.ToUTF8().data(),false);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("WNodeManager::onProcessAllTimerEvent: %s") , e.what()).utf8_string());
        }

        (*iter).second.starttime=0;
        ++iter;
    }
}
